# -*- coding: utf-8 -*-
# tcp mapping 

import sys          # 导入系统相关模块
import socket       # 导入网络通信模块
import logging      # 导入日志模块
import threading    # 导入线程模块

# 接收数据缓存大小
PKT_BUFF_SIZE = 10240  # 定义数据包缓冲区大小为10KB

# 创建日志记录器实例
logger = logging.getLogger("Proxy Logging")
# 创建日志格式化器，定义日志输出格式
formatter = logging.Formatter('%(name)-12s %(asctime)s %(levelname)-8s %(lineno)-4d %(message)s', '%Y %b %d %a %H:%M:%S',)

# 创建流处理器，将日志输出到标准错误输出
stream_handler = logging.StreamHandler(sys.stderr)
# 设置日志格式化器
stream_handler.setFormatter(formatter)
# 将处理器添加到日志记录器
logger.addHandler(stream_handler)
# 设置日志级别为DEBUG
logger.setLevel(logging.DEBUG)

# 单向流数据传递函数
def tcp_mapping_worker(conn_receiver, conn_sender):
    logger.info("start ")  # 记录开始日志
    while True:  # 循环处理数据传输
        try:
            # 从接收连接中接收数据
            data = conn_receiver.recv(PKT_BUFF_SIZE)
        except Exception as e:
            # 捕获异常并记录错误日志
            logger.debug(e)
            logger.debug('Connection closed.')
            break  # 连接异常则退出循环

        if not data:
            # 如果没有接收到数据，说明连接已断开
            logger.info('No more data is received.') # 正常情况下不会到这，一般是某个连接断了
            break

        try:
            # 将接收到的数据发送到目标连接
            conn_sender.sendall(data)
        except Exception:
            # 发送失败时记录错误日志
            logger.error('Failed sending data.')
            break

        # 记录数据传输日志（被注释掉）
        # logger.info('Mapping data > %s ' % repr(data))
        # logger.info('Mapping > %s -> %s > %d bytes.' % (conn_receiver.getpeername(), conn_sender.getpeername(), len(data)))

    # 关闭两个连接
    conn_receiver.close()
    conn_sender.close()

    return  # 函数返回


# 端口映射请求处理函数
def join(connA, connB):
    # 创建两个线程分别处理两个连接间的数据传输
    threading.Thread(target=tcp_mapping_worker, args=(connA, connB)).start()
    threading.Thread(target=tcp_mapping_worker, args=(connB, connA)).start()
    return  # 函数返回

# 主程序入口
if __name__ == '__main__':
    # 测试代码
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建TCP套接字
    sock.bind(('0.0.0.0', 8080))  # 绑定到本地8080端口
    # sock.setblocking(False)  # 设置为非阻塞模式（被注释）
    sock.listen(100)  # 监听连接，最大连接数为100
    conn1,addr1 =sock.accept()  # 接受第一个客户端连接

    sock2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建第二个TCP套接字
    sock2.bind(('0.0.0.0', 7000))  # 绑定到本地7000端口
    sock2.listen(100)  # 监听连接，最大连接数为100

    # 类似frpc，创建到7000端口的连接
    server_conn = socket.create_connection(('localhost', 7000))

    conn2,addr2 =sock2.accept()  # 接受第二个客户端连接
    join(conn1,conn2)  # 建立conn1和conn2之间的双向数据传输

    target_conn = socket.create_connection(('192.168.1.101', 3389))  # 创建到目标服务器的连接
    join(server_conn,target_conn)  # 建立server_conn和target_conn之间的双向数据传输

